#include <string.h>
#include "wifi.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"

#include "esp_heap_caps.h"
// #include "esp_blufi_api.h"
#include "lwip/err.h"
#include "lwip/sys.h"

#include "ntp.h"

const char *TAG_WIFI = "WIFI_INFO";
EventGroupHandle_t wifi_event_group;
wifi_config_t sta_config;
_Cur_wifi_info cur_wifi_info;
_Cur_wifi_list cur_wifi_list;

static void ip_event_handler(void *arg, esp_event_base_t event_base,
                             int32_t event_id, void *event_data)
{

    switch (event_id)
    {
    case IP_EVENT_STA_GOT_IP:
    {
        ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
        cur_wifi_info.ip_info = event->ip_info;
        xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT);
        cur_wifi_info.isConnected = true;
        break;
    }
    default:
        break;
    }
    return;
}

static void wifi_event_handler(void *arg, esp_event_base_t event_base,
                               int32_t event_id, void *event_data)
{
    ESP_LOGI(TAG_WIFI,"EVENT_ID:%ld",event_id);

    switch (event_id)
    {
    case WIFI_EVENT_STA_START:
        esp_wifi_disconnect();
        esp_wifi_connect();
        
        break;
    case WIFI_EVENT_STA_CONNECTED:
        cur_wifi_info.isConnected = true;
        wifi_event_sta_connected_t *event = (wifi_event_sta_connected_t *)event_data;
        memcpy(cur_wifi_info.bssid, event->bssid, 6);
        memcpy(cur_wifi_info.ssid, event->ssid, event->ssid_len);
        cur_wifi_info.ssid_len = event->ssid_len;
        sntp_time_init();
        break;
    case WIFI_EVENT_STA_DISCONNECTED:
        memset(cur_wifi_info.ssid, 0, 32);
        memset(cur_wifi_info.bssid, 0, 6);
        cur_wifi_info.isConnected = false;
        xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT);
        ESP_LOGI(TAG_WIFI, "WiFi连接断开");
        if (!cur_wifi_info.isUserDisconnetAP)
        {
            esp_wifi_connect();
            ESP_LOGI(TAG_WIFI, "尝试重连");
            xEventGroupWaitBits(
                wifi_event_group,           // 事件组
                WIFI_CONNECTED_BIT,         // 等待的位
                pdTRUE,                     //运行前是否清空
                pdFALSE,                    // 是否等待所有位被置为
                5000 / portTICK_PERIOD_MS); // 设置最长等待时间
            if ((xEventGroupGetBits(wifi_event_group) & WIFI_CONNECTED_BIT) == WIFI_CONNECTED_BIT)
            {
                ESP_LOGI(TAG_WIFI,"WiFi链接成功置位");
            }
            else
            {
                ESP_LOGI(TAG_WIFI, "连接失败,再次重连");
                esp_wifi_disconnect();
                esp_wifi_connect();
            }
        }
        break;
    case WIFI_EVENT_AP_START:

        break;

    case WIFI_EVENT_SCAN_DONE:
    {
        uint16_t apCount = 0;
        esp_wifi_scan_get_ap_num(&apCount);
        if (apCount == 0)
        {
            xEventGroupSetBits(wifi_event_group, WIFI_FAIL_BIT);
            break;
        }
        cur_wifi_list.apCount = apCount;
        // if(cur_wifi_list.ap_list!=NULL){
        //     free(cur_wifi_list.ap_list);
        // }
        cur_wifi_list.ap_list = (wifi_ap_record_t *)heap_caps_malloc(sizeof(wifi_ap_record_t) * apCount,MALLOC_CAP_SPIRAM);
        if (!cur_wifi_list.ap_list)
        {
            ESP_LOGI(TAG_WIFI, "wifi_ap_record_t内存开辟失败apCount:%d", apCount);
            xEventGroupSetBits(wifi_event_group, WIFI_FAIL_BIT);
            break;
        }
        ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&apCount, cur_wifi_list.ap_list));
        xEventGroupSetBits(wifi_event_group, WIFI_SCAN_FINISH_BIT);
        esp_wifi_scan_stop();
        ////////
        // esp_blufi_ap_record_t * blufi_ap_list = (esp_blufi_ap_record_t *)malloc(apCount * sizeof(esp_blufi_ap_record_t));
        // if (!blufi_ap_list) {
        //     if (ap_list) {
        //         free(ap_list);
        //     }
        //     BLUFI_ERROR("malloc error, blufi_ap_list is NULL");
        //     break;
        // }
        // for (int i = 0; i < apCount; ++i)
        // {
        //     blufi_ap_list[i].rssi = ap_list[i].rssi;
        //     memcpy(blufi_ap_list[i].ssid, ap_list[i].ssid, sizeof(ap_list[i].ssid));
        // }

        // if (ble_is_connected == true) {
        //     esp_blufi_send_wifi_list(apCount, blufi_ap_list);
        // } else {
        //     BLUFI_INFO("BLUFI BLE is not connected yet\n");
        //}
        ////////

        break;
    }
    // case WIFI_EVENT_AP_STACONNECTED:
    //     wifi_event_ap_staconnected_t* eevent = (wifi_event_ap_staconnected_t*) event_data;
    //     ESP_LOGI(TAG_WIFI, "station "MACSTR" join, AID=%d",MAC2STR(eevent->mac), eevent->aid);
    //     break;
    // case WIFI_EVENT_AP_STADisConnected:
    //     wifi_event_ap_stadisConnected_t* eevent = (wifi_event_ap_stadisConnected_t*) event_data;
    //     ESP_LOGI(TAG_WIFI, "station "MACSTR" leave, AID=%d",MAC2STR(eevent->mac), eevent->aid);
    //     break;
    default:
        break;
    }
    return;
}

void init_wifi()
{

    cur_wifi_info.isConnected = false;
    cur_wifi_info.isUserDisconnetAP = false;
    ESP_ERROR_CHECK(esp_netif_init());
    wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);
    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &ip_event_handler, NULL));

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_start());
}

/**
 * @brief   连接WIFI
 *
 * @param   config  wifi_config_t 配置
 * **/
void connect_wifi(wifi_config_t *config)
{
    cur_wifi_info.isUserDisconnetAP = false;
    esp_wifi_set_config(WIFI_IF_STA, config);
};

void disconnect_wifi()
{
    cur_wifi_info.isUserDisconnetAP = true;
    esp_wifi_disconnect();
}
void wifi_scan_start()
{
    const wifi_scan_config_t scanConf = {
        .ssid = NULL,
        .bssid = NULL,
        .channel = 0,
        .show_hidden = true};
    esp_wifi_scan_start(&scanConf, false);
}
void wifi_scan_stop()
{

}
void wifi_scan_get_res()
{
}
